package online

import (
	"fmt"

	"server/common"

	"github.com/mitchellh/mapstructure"
	"github.com/sirupsen/logrus"
)

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) checkLoginReqData(data common.LoginReqData) error {
	// Check if user ID is provided
	if data.UserId == "" {
		return fmt.Errorf("user ID is required in login request")
	}

	// Check if user exists
	if s.userMgr.UserExists(data.UserId) {
		return fmt.Errorf("user %s already exists", data.UserId)
	}

	return nil
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) sendSuccessLoginResponse(rid string, userId string, from common.ServiceInfo,
	connId string) {

	userList := onlineService.userMgr.GetUserListWithoutSelf(userId)
	userIdList := make([]string, 0, len(userList))
	for _, user := range userList {
		userIdList = append(userIdList, user.UserId)
	}

	resMsg := common.Message{
		Cmd: common.LOGIN_RES,
		Rid: rid,
		Data: common.ResMsgData{
			Code: 0,
			Msg:  "logged in successfully",
			Data: common.LoginResData{
				UserId: userId,
				Users:  userIdList,
			},
		},
	}
	s.dispatcher.Dispatch(resMsg, s.serviceInfo, from, connId)
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) sendFailureLoginResponse(rid string, msg string, from common.ServiceInfo,
	connId string) {

	resMsg := common.Message{
		Cmd: common.LOGIN_RES,
		Rid: rid,
		Data: common.ResMsgData{
			Code: 1,
			Msg:  msg,
		},
	}
	s.dispatcher.Dispatch(resMsg, s.serviceInfo, from, connId)
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) handleLoginReq(msg common.Message, from common.ServiceInfo,
	connId string) error {
	common.Logger(common.SERVICE_TYPE_ONLINE, msg.Rid).WithFields(logrus.Fields{
		"msg":    common.ToJson(msg),
		"from":   from,
		"connId": connId,
	}).Info("call handleLoginRequest")

	var loginData common.LoginReqData
	if err := mapstructure.Decode(msg.Data, &loginData); err != nil {
		common.Logger(common.SERVICE_TYPE_ONLINE, msg.Rid).WithError(err).
			Error("failed to parse login request")
		s.sendFailureLoginResponse(msg.Rid, "invalid login request data", from, connId)
		return nil
	}

	if err := s.checkLoginReqData(loginData); err != nil {
		common.Logger(common.SERVICE_TYPE_ONLINE, msg.Rid).WithError(err).
			Error("invalid login request data")
		s.sendFailureLoginResponse(msg.Rid, err.Error(), from, connId)
		return nil
	}

	onlineService.userMgr.AddUser(loginData.UserId, from, connId)

	s.sendSuccessLoginResponse(msg.Rid, loginData.UserId, from, connId)

	// Notify other users about the new user
	for _, user := range onlineService.userMgr.GetUserListWithoutSelf(loginData.UserId) {
		notifyMsg := common.Message{
			Cmd: common.LOGIN_NOTIFY,
			Rid: msg.Rid,
			Data: common.LoginNotifyData{
				UserId: loginData.UserId,
			},
		}
		s.dispatcher.DispatchWait(notifyMsg, s.serviceInfo, user.ServiceInfo, user.ConnId,
			common.LOGIN_ACK)
	}

	return nil
}
